﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.RsaKeyGen
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.IO;
using System.Security.Cryptography;

namespace Microsoft.InfoCards
{
  internal sealed class RsaKeyGen
  {
    private static int[] hashesToWriteP = new int[8]
    {
      2,
      12,
      11,
      10,
      0,
      6,
      5,
      4
    };
    private static int[] numBytesToWriteP = new int[8]
    {
      4,
      20,
      20,
      20,
      4,
      20,
      20,
      20
    };
    private static int[] srcIndexBytesToWriteP = new int[8]
    {
      16,
      0,
      0,
      0,
      16,
      0,
      0,
      0
    };
    private static int[] hashesToWriteQ = new int[8]
    {
      3,
      15,
      14,
      13,
      1,
      9,
      8,
      7
    };
    private static int[] numBytesToWriteQ = RsaKeyGen.numBytesToWriteP;
    private static int[] srcIndexBytesToWriteQ = RsaKeyGen.srcIndexBytesToWriteP;
    private static RijndaelManaged s_rjAes128 = new RijndaelManaged();
    private const int Xpq12Length = 14;
    private const int XpqLength = 128;
    private const int NumberOfSha1Hashes = 16;
    private const int InfoCardKeyLength = 2048;
    private const int HnLength = 20;
    private const int PublicExponentValue = 65537;
    private const string Aes128EncryptionKey = "f561e58b-3ebc-4e0c-940d-0a6ddc219dfd";
    private const int ByteForHundredthBit = 12;

    static RsaKeyGen()
    {
      RsaKeyGen.s_rjAes128.Mode = CipherMode.ECB;
      RsaKeyGen.s_rjAes128.Padding = PaddingMode.Zeros;
      RsaKeyGen.s_rjAes128.Key = new Guid("f561e58b-3ebc-4e0c-940d-0a6ddc219dfd").ToByteArray();
    }

    public static byte[] CreateRsaKeyPairX931(byte[] masterKey, byte[] targetId)
    {
      InfoCardTrace.Assert(true, "Only 2048 bit key sizes supported");
      byte[][] hn = RsaKeyGen.CalculateHn(masterKey, targetId);
      byte[] numArray1 = (byte[]) null;
      byte[] numArray2 = new byte[14];
      byte[] numArray3 = new byte[14];
      byte[] numArray4 = new byte[14];
      byte[] numArray5 = new byte[14];
      byte[] numArray6 = new byte[128];
      byte[] numArray7 = new byte[128];
      Array.Copy((Array) hn[0], 0, (Array) numArray2, 0, numArray2.Length);
      Array.Copy((Array) hn[1], 0, (Array) numArray3, 0, numArray3.Length);
      Array.Copy((Array) hn[2], 0, (Array) numArray4, 0, numArray4.Length);
      Array.Copy((Array) hn[3], 0, (Array) numArray5, 0, numArray5.Length);
      RsaKeyGen.WriteToArray(RsaKeyGen.hashesToWriteP, RsaKeyGen.numBytesToWriteP, RsaKeyGen.srcIndexBytesToWriteP, hn, numArray6);
      RsaKeyGen.WriteToArray(RsaKeyGen.hashesToWriteQ, RsaKeyGen.numBytesToWriteQ, RsaKeyGen.srcIndexBytesToWriteQ, hn, numArray7);
      try
      {
        KeyGenRestartCodes restartCode = KeyGenRestartCodes.X931RestartNone;
        do
        {
          numArray6[(int) sbyte.MaxValue] |= (byte) 192;
          numArray7[(int) sbyte.MaxValue] |= (byte) 192;
          numArray2[12] |= (byte) 16;
          numArray3[12] |= (byte) 16;
          numArray4[12] |= (byte) 16;
          numArray5[12] |= (byte) 16;
          numArray1 = NativeMcppMethods.X931KeyGenWrapper(numArray2, numArray3, numArray4, numArray5, numArray6, numArray7, 65537, ref restartCode);
          switch (restartCode)
          {
            case KeyGenRestartCodes.X931RestartNone:
              InfoCardTrace.Assert(null != numArray1, "Cryptoblob should not be null since API succeeded");
              break;
            case KeyGenRestartCodes.X931RestartDTooSmall:
              InfoCardTrace.Assert(null == numArray1, "Cryptoblob should be null");
              InfoCardTrace.Assert(false, "Not expected for d < 2^1024 with e = 65537");
              RsaKeyGen.InfoCardRegenerateParam(numArray4);
              RsaKeyGen.InfoCardRegenerateParam(numArray5);
              RsaKeyGen.InfoCardRegenerateParam(numArray7);
              break;
            case KeyGenRestartCodes.X931RestartNonTrivialGcd:
              InfoCardTrace.Assert(null == numArray1, "Cryptoblob should be null");
              RsaKeyGen.InfoCardRegenerateParam(numArray2);
              RsaKeyGen.InfoCardRegenerateParam(numArray3);
              RsaKeyGen.InfoCardRegenerateParam(numArray4);
              RsaKeyGen.InfoCardRegenerateParam(numArray5);
              break;
            case KeyGenRestartCodes.X931RestartPQOverflow:
              InfoCardTrace.Assert(null == numArray1, "Cryptoblob should be null");
              RsaKeyGen.InfoCardRegenerateParam(numArray6);
              RsaKeyGen.InfoCardRegenerateParam(numArray7);
              break;
            case KeyGenRestartCodes.X931RestartPQ12OverFlow:
              InfoCardTrace.Assert(null == numArray1, "Cryptoblob should be null");
              RsaKeyGen.InfoCardRegenerateParam(numArray2);
              RsaKeyGen.InfoCardRegenerateParam(numArray3);
              RsaKeyGen.InfoCardRegenerateParam(numArray4);
              RsaKeyGen.InfoCardRegenerateParam(numArray5);
              break;
            case KeyGenRestartCodes.X931RestartXpXqClose:
              InfoCardTrace.Assert(null == numArray1, "Cryptoblob should be null");
              RsaKeyGen.InfoCardRegenerateParam(numArray7);
              break;
          }
        }
        while (restartCode != KeyGenRestartCodes.X931RestartNone);
        InfoCardTrace.Assert(null != numArray1, "Cryptoblob should NOT be null outside while loop");
      }
      finally
      {
        Array.Clear((Array) numArray2, 0, numArray2.Length);
        Array.Clear((Array) numArray3, 0, numArray3.Length);
        Array.Clear((Array) numArray4, 0, numArray4.Length);
        Array.Clear((Array) numArray5, 0, numArray5.Length);
        Array.Clear((Array) numArray6, 0, numArray6.Length);
        Array.Clear((Array) numArray7, 0, numArray7.Length);
      }
      return numArray1;
    }

    private static void WriteToArray(
      int[] hashesToWrite,
      int[] numBytesToWrite,
      int[] srcIndexBytesToWrite,
      byte[][] sourceArrayOfHashes,
      byte[] destArray)
    {
      InfoCardTrace.Assert(hashesToWrite.Length == numBytesToWrite.Length, "Size must be equal");
      InfoCardTrace.Assert(numBytesToWrite.Length == srcIndexBytesToWrite.Length, "Size must be equal");
      int destinationIndex = 0;
      for (int index1 = 0; index1 < hashesToWrite.Length; ++index1)
      {
        int index2 = hashesToWrite[index1];
        Array.Copy((Array) sourceArrayOfHashes[index2], srcIndexBytesToWrite[index1], (Array) destArray, destinationIndex, numBytesToWrite[index1]);
        destinationIndex += numBytesToWrite[index1];
      }
    }

    private static byte[][] CalculateHn(byte[] masterKey, byte[] subjectEntropy)
    {
      byte[][] numArray = new byte[16][];
      byte[] buffer = new byte[masterKey.Length + subjectEntropy.Length + 4];
      Array.Copy((Array) masterKey, 0, (Array) buffer, 0, masterKey.Length);
      Array.Copy((Array) subjectEntropy, 0, (Array) buffer, masterKey.Length, subjectEntropy.Length);
      for (uint index = 0; (long) index < (long) numArray.Length; ++index)
      {
        InfoCardTrace.Assert(index <= (uint) byte.MaxValue, "n must fit in a byte.");
        InfoCardTrace.Assert(buffer.Length - 1 == masterKey.Length + subjectEntropy.Length + 3, "Index location of n must be last element of array.");
        buffer[buffer.Length - 1] = (byte) index;
        numArray[(IntPtr) index] = SHA1.Create().ComputeHash(buffer);
        Array.Reverse((Array) numArray[(IntPtr) index]);
      }
      Array.Clear((Array) buffer, 0, buffer.Length);
      return numArray;
    }

    private static void InfoCardRegenerateParam(byte[] prevBytes)
    {
      byte[] numArray = RsaKeyGen.AESEncryptECB(prevBytes);
      Array.Copy((Array) numArray, 0, (Array) prevBytes, 0, prevBytes.Length);
      Array.Clear((Array) numArray, 0, numArray.Length);
    }

    private static byte[] AESEncryptECB(byte[] plaintextbyte)
    {
      MemoryStream memoryStream = new MemoryStream();
      CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, RsaKeyGen.s_rjAes128.CreateEncryptor(), CryptoStreamMode.Write);
      cryptoStream.Write(plaintextbyte, 0, plaintextbyte.Length);
      cryptoStream.Close();
      byte[] array = memoryStream.ToArray();
      memoryStream.Close();
      return array;
    }

    private RsaKeyGen()
    {
    }
  }
}
